﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using FinalPointSet.Model.Asset;
using FinalPointSet.Model.Constant;
using FinalPointSet.Model.Constant.Message;
using FinalPointSet.Model.Constants;
using FinalPointSet.Model.Manager;
using ICSharpCode.AvalonEdit.Highlighting;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows;
using static FinalPointSet.Model.Manager.MessageManager;

namespace FinalPointSet.ViewModel.Page.MainView
{
    public partial class GroupingSetsPageViewModel : ObservableObject
    {
        /// <summary>
        /// 输入的维度
        /// </summary>
        [ObservableProperty]
        private string _InputDims = "";
        /// <summary>
        /// 指定的维度组合
        /// </summary>
        [ObservableProperty]
        private string _TargetDims = "";
        /// <summary>
        /// 输出的SQL
        /// </summary>
        [ObservableProperty]
        private string _targetSQL = "";
        /// <summary>
        /// 高亮样式
        /// </summary>
        [ObservableProperty]
        private IHighlightingDefinition? _highlightingDefinition;
        /// <summary>
        /// 复制按钮可见性
        /// </summary>
        [ObservableProperty]
        private Visibility _CopyButtonVisibility = Visibility.Hidden;
        public GroupingSetsPageViewModel()
        {
            //设置代码高亮
            ObjectPair<IHighlightingDefinition>? hightLightDef = AssetManager.Instance.GetObjectListElementByKey<IHighlightingDefinition>(Path.HighLightDefinition, "SQL");
            if (hightLightDef != null)
            {
                HighlightingDefinition = hightLightDef.Value;
            }
        }

        private const int MaxInputDimCount = 8;
        [RelayCommand]
        public void Transform()
        {
            Debug.Print($"输入SQL={InputDims}");
            if (string.IsNullOrEmpty(InputDims))
            {
                Broadcast(MsgType.GrowMsg, new GrowMsgArg(WindowType.MainView, GrowlMsgType.Warning, $"输维度不能为空!"));
                return;
            }
            //清洗输入
            List<string> list_input = InputDims
                                        .ToLower()
                                        .Replace("group by", "")
                                        .Trim()
                                        .Replace(" ", "")
                                        .Replace("\n", "")
                                        .Replace("\r", "")
                                        .Split(",")
                                        .ToList();
            //校验输入的维度个数和是否指定维度
            if (list_input.Count >= MaxInputDimCount && string.IsNullOrEmpty(TargetDims))
            {
                Broadcast(MsgType.GrowMsg, new GrowMsgArg(WindowType.MainView, GrowlMsgType.Warning, $"当前维度超过{MaxInputDimCount}个, 生成的组合值过多, 请输入指定维度组合!"));
                return;
            }

            try
            {
                //判断是否指定目标维度组合
                if (string.IsNullOrEmpty(TargetDims))
                {
                    TargetSQL = GenerateGroupingSetsWithoutTargetDims(list_input);
                }
                else
                {
                    List<List<string>> splitedTargetDims = SplitTargetDimByLine(TargetDims);
                    TargetSQL = GenarteGroupingSetsHasTargetDims(list_input, splitedTargetDims);
                }
            }
            catch (Exception e)
            {
                Broadcast(MsgType.GrowMsg, new GrowMsgArg(WindowType.MainView, GrowlMsgType.Error, $"转换失败! 错误原因:{e.Message}"));
                return;
            }

            try
            {
                if (string.IsNullOrEmpty(TargetSQL))
                    return;

                Copy();
                CopyButtonVisibility = Visibility.Visible;
            }
            catch (Exception e)
            {

                Debug.Print($"GroupingSetsPageViewModel.Transform(), 拷贝结果到剪贴板失败, 原因: {e.Message}");
            }

            Debug.Print($"GroupingSetsPageViewModel.Transform(). 输出SQL={TargetSQL}");
        }

        [RelayCommand]
        public void Reset()
        {
            InputDims = string.Empty;
            TargetDims = string.Empty;
            TargetSQL = string.Empty;
            CopyButtonVisibility = Visibility.Hidden;
        }

        /// <summary>
        /// 复制结果
        /// </summary>
        [RelayCommand]
        private void Copy()
        {
            if (!string.IsNullOrEmpty(TargetSQL))
            {
                Clipboard.SetText(TargetSQL);
                Broadcast(MsgType.GrowMsg, new GrowMsgArg(WindowType.MainView, GrowlMsgType.Success, $"生成成功, 已复制结果到剪贴板"));
            }
        }

        /// <summary>
        /// 生成维度组合,指定目标维度组合
        /// </summary>
        /// <param name="dims"></param>
        /// <param name="splitedTargetDims"></param>
        /// <returns></returns>
        private string GenarteGroupingSetsHasTargetDims(List<string> dims, List<List<string>> splitedTargetDims)
        {
            //格式化输出
            string resultCaseWhen = FormatOutputCaseWhen(dims, splitedTargetDims);
            string resultGrouping = FormatOutputReuslt(dims, splitedTargetDims);
            return $"{resultCaseWhen}{resultGrouping}";
        }

        /// <summary>
        /// 生成目标维度组合,不指定目标维度组合
        /// </summary>
        /// <param name="dims"></param>
        /// <returns></returns>
        private string GenerateGroupingSetsWithoutTargetDims(List<string> dims)
        {
            //提取全部组合
            List<List<string>> allCombinations = GenerateGroupingSetsCombinations(dims);
            return GenarteGroupingSetsHasTargetDims(dims, allCombinations);
        }

        /// <summary>
        /// 生成所有可多维度组合的情况
        /// </summary>
        /// <param name="columns">全部分组维度集合</param>
        /// <returns>所有可多维度组合的情况</returns>
        private List<List<string>> GenerateGroupingSetsCombinations(List<string> columns)
        {
            List<List<string>> result = new();
            List<string> current = new();
            int n = columns.Count;

            GenerateCombinations(columns, n, 0, current, result);

            return result;
        }

        /// <summary>
        /// 生成当前的维度组合
        /// </summary>
        /// <param name="columns"></param>
        /// <param name="n"></param>
        /// <param name="start"></param>
        /// <param name="current"></param>
        /// <param name="result"></param>
        private void GenerateCombinations(List<string> columns, int n, int start, List<string> current, List<List<string>> result)
        {
            if (start == n)
            {
                result.Add(new List<string>(current));
                return;
            }

            current.Add(columns[start]);
            GenerateCombinations(columns, n, start + 1, current, result);
            current.RemoveAt(current.Count - 1);

            GenerateCombinations(columns, n, start + 1, current, result);
        }


        /// <summary>
        /// 提取当前元素位于集合的下标
        /// </summary>
        /// <param name="columns">全部分组维度集合</param>
        /// <param name="element">当前元素</param>
        /// <returns>当前元素的下标</returns>
        private int GetElementIndex(List<string> columns, string element)
        {
            for (int i = 0; i < columns.Count; i++)
            {
                if (columns[i].Equals(element))
                {
                    return i;
                }
            }
            return -1;
        }

        /// <summary>
        /// 获取grouping__id
        /// </summary>
        /// <param name="columns">全部分组统计维度</param>
        /// <param name="combination">当前的统计维度组合</param>
        /// <returns>grouping__id</returns>
        private string GetGroupingID(List<string> columns, List<string> combination)
        {
            // 维度真实权重
            List<int> list_weight = Enumerable.Range(0, columns.Count).Select(i => (int)Math.Pow(2, columns.Count - 1 - i)).ToList();
            //判断输入的目标维度是否全部属于维度,若不是,则说明指定的目标维度输入存在错误,此时直接返回获取失败
            if (!IsSubSet(columns, combination))
            {
                return "获取分组ID失败,请检查指定的维度组合输入是否有误!";
            }
            //提取未选择的维度置高位(选择的置低位)
            List<string> list_unselected = columns.Except(combination).ToList();
            //遍历,累加权重,得到分组ID
            int groupingId = 0;
            for (int i = 0; i < list_unselected.Count; i++)
            {
                int index = GetElementIndex(columns, list_unselected[i]);

                int weight = list_weight[index];
                groupingId += weight;
            }
            return groupingId.ToString();
        }

        /// <summary>
        /// 切分、清洗输入的指定维度
        /// </summary>
        /// <param name="targetDim"></param>
        /// <returns></returns>
        private List<List<string>> SplitTargetDimByLine(string targetDim)
        {
            //根据换行符,切割目标维度组合
            string[] etlTargetDims = targetDim.Replace(" ", "").Replace("\r", "").Split("\n");
            //根据逗号,切割每行维度组合为一个一个的维度值,便于计算权重
            List<List<string>> splitedTargetDims = new();
            foreach (string item in etlTargetDims)
            {
                splitedTargetDims.Add(
                    item.Replace(",(", "")
                        .Replace("(", "")
                        .Replace("),", "")
                        .Replace(")", "")
                        .Split(',').ToList());
            }
            return splitedTargetDims;
        }

        /// <summary>
        /// 格式化维度组合输出的字符串
        /// </summary>
        /// <param name="dims"></param>
        /// <param name="splitedTargetDims"></param>
        /// <returns></returns>
        private string FormatOutputReuslt(List<string> dims, List<List<string>> splitedTargetDims)
        {
            //遍历结果,提取元素与找到当前最长的字符串
            List<string> list_grouping_nm = new();
            List<string> list_grouping_id = new();
            List<bool> outputFlagList = new();
            int i_max_str = 0;
            //遍历目标维度集合, 找出维度组合最长字符串
            foreach (List<string> targetDim in splitedTargetDims)
            {
                string grouping_nm = $"({string.Join(", ", targetDim)})";
                string grouping_id = GetGroupingID(dims, targetDim);
                list_grouping_nm.Add(grouping_nm);
                list_grouping_id.Add(grouping_id);
                if (grouping_nm.Length > i_max_str)
                {
                    i_max_str = grouping_nm.Length;
                }
            }

            //遍历拼接group by语句
            StringBuilder sb_result = new($"group by {dims[0]}\n");
            string s_group_space = new(' ', 8);
            for (int i = 1; i < dims.Count; i++)
            {
                sb_result.AppendLine($"{s_group_space},{dims[i]}");
            }

            //遍历结果,格式化输出
            string s_span = new(' ', 4);
            StringBuilder sb_grouping_sets = new("grouping sets (\n");
            for (int i = 0; i < list_grouping_nm.Count; i++)
            {
                string grouping_nm = list_grouping_nm[i];
                string grouping_id = list_grouping_id[i];
                int i_cur_len = grouping_nm.Length;
                string s_space = new(' ', i_max_str - i_cur_len);
                string s_cur_str;
                if (i == 0)
                {
                    s_cur_str = $"{s_span} {grouping_nm}{s_space}{s_span}--grouping__id = {grouping_id}";
                }
                else
                {
                    s_cur_str = $"{s_span},{grouping_nm}{s_space}{s_span}--grouping__id = {grouping_id}";
                }
                sb_grouping_sets.AppendLine(s_cur_str);
            }
            sb_grouping_sets.Append(')');
            sb_result.Append(sb_grouping_sets);
            return sb_result.ToString();
        }

        /// <summary>
        /// 格式化输出,获取case when判断语句
        /// </summary>
        /// <param name="dims"></param>
        /// <param name="splitedTargetDims"></param>
        /// <returns></returns>
        private string FormatOutputCaseWhen(List<string> dims, List<List<string>> splitedTargetDims)
        {
            StringBuilder result = new("case");
            //遍历获取最大grouping_id, 便于最后格式化输出美观
            int maxLength = 0;
            for (int i = 0; i < splitedTargetDims.Count; i++)
            {
                string grouping_id = GetGroupingID(dims, splitedTargetDims[i]).ToString();
                if (grouping_id.Length > maxLength)
                {
                    maxLength = grouping_id.Length;
                }
            }
            //遍历结果,格式化输出
            string s_span = new(' ', 5);
            for (int i = 0; i < splitedTargetDims.Count; i++)
            {
                string grouping_id = GetGroupingID(dims, splitedTargetDims[i]);
                int curLength = grouping_id.ToString().Length;
                string cuSpace = new(' ', maxLength - curLength);
                string line = $"when grouping__id = {grouping_id}{cuSpace} then ''";
                if (i == 0)
                {
                    result.AppendLine($" {line}");
                }
                else
                {
                    result.AppendLine($"{s_span}{line}");
                }
            }
            result.AppendLine("end as grouping_flag");
            return result.ToString();
        }

        /// <summary>
        /// 判断输入的维度组合是否是所有维度的子集(用于判断输入目标维度与维度不一致的情况)
        /// </summary>
        /// <param name="columns"></param>
        /// <param name="combination"></param>
        /// <returns></returns>
        private bool IsSubSet(List<string> columns, List<string> combination)
        {
            HashSet<string> hasSetColumns = new(columns);
            HashSet<string> hasSetCombinations = new(combination);
            if ((combination.Count == 1 && "".Equals(combination[0])) || hasSetCombinations.IsSubsetOf(hasSetColumns))
            {
                return true;
            }
            return false;
        }
    }
}
